﻿<?php
declare(ticks = 1);


function debug_log($msg,$from='DEBUG'){
        global $logfile,$debug;
        //if ($debug==true) error_log(date('d.m.Y h:i:s')." ".$from.": ".$msg, 3, $logfile);
        if ($debug==true) echo date('d.m.Y h:i:s')." ".$from.": ".$msg."\n";
}
include ('Thread.php');
include ('msg_queue.php');
//-------------------------------------------------------------------------------------
function s1_handler ($_signal,$runnable,$sigHandler){
        global $przerwij;
        debug_log("Przerwanie pracy",$runnable);
        switch ($runnable){
                case 'proc1':
                        $przerwij=true;
                           break;
                case 'proc2':
                        $przerwij=true;
                                break;
                case 'proc3':
                $przerwij=true;
                                break;    
        }
                }
//-------------------------------------------------------------------
function s2_handler ($_signal,$runnable,$sigHandler){
        global $stop;
        debug_log("Zatrzymanie pracy",$runnable);
        switch ($runnable){
                case 'proc1':
        
                $stop=true;
                            break;
                case 'proc2':
        
                $stop=true;
                                break;
                case 'proc3':
        
                $stop=true;
                                break;    
        }
        
        }
//-------------------------------------------------------------------
function s3_handler ($_signal,$runnable,$sigHandler){
                global $stop;
                debug_log("Wznowienie pracy",$runnable);
                $stop=false;
        switch ($runnable){
                case 'proc1':
                        $stop=false;
                            break;
                case 'proc2':
                        $stop=false;
                                break;
                case 'proc3':
                        $stop=false;
                                break;    
        }
        }
//-------------------------------------------------------------------
function pm_handler($_signal,$runnable,$sigHandler){
        global $nrproc,$sig1,$sig2,$sig3,$sig4,$sasiedzi;
        $nrproc=0;
        switch ($_signal){
                case $sig1:
                        debug_log("Przerwanie pracy procesów potomnych",$runnable);
                        posix_kill($sasiedzi[$nrproc+2],$sig1);
                        posix_kill($sasiedzi[$nrproc+1],$sig1);
                        posix_kill($sasiedzi[$nrproc],$sig1);
                        break;
                case $sig2:
                        debug_log("Zatrzymanie pracy procesów potomnych",$runnable);
                        debug_log("Proces 3");
						posix_kill($sasiedzi[$nrproc+2],$sig2);
						//fwrite(mkpipe($FIFO2,"w") ,NULL);
						sleep(2);
						debug_log("Proces 2");
                        posix_kill($sasiedzi[$nrproc+1],$sig2);
						sleep(2);
						debug_log("Proces 1");
                        posix_kill($sasiedzi[$nrproc],$sig2);
                        
                        break;
                case $sig3:
                    debug_log("Wznowienie pracy procesów potomnych",$runnable);
                        posix_kill($sasiedzi[$nrproc+2],$sig3);
                        posix_kill($sasiedzi[$nrproc+1],$sig3);
                        posix_kill($sasiedzi[$nrproc],$sig3);
                        break;
        }
        
        
}
//----------------------------------------------------------------------------------------
function czekaj_SasiedziPID($key) {
        global $sasiedzi;
        $msg=array();
        debug_log('Czekam na pidy sąsiadów','INIT');
        receive_message($key, $sasiedzi);
        debug_log('Pidy sasiadow:'.var_dump($sasiedzi),'INIT');
		sleep(1);
}


//function s0_proc($_signal,$runnable,$sigHandler){
//pcntl_signal( SIGUSR2,function ($signo){echo "Caught a singal2 $signo".PHP_EOL;});
//----------------------------------------------------------------------------------------


function mkpipe($pipe='',$mode="r+"){
        if ($pipe=='') return -1;
        $fmode=0600;
   if(!file_exists($pipe)) {
      // tworz rurę
      umask(0);
      posix_mkfifo($pipe,$fmode);
   }
          return fopen($pipe,$mode); // zwróć handle pliku fifo
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
//* czytanie z STDIN i wysyałanie do FIFO1
function proc1(){
        global $sasiedzi,$stop,$start,$przerwij,$sig1,$sig2,$sig3,$sig4,$nrproc,$FIFO1,$FIFO2,$msg_key1,$msg_key2,$msg_key3;
        czekaj_SasiedziPID($msg_key1);
        
        $pipe=mkpipe($FIFO1,"w");
        $fp=fopen("php://stdin","r");
        while (!feof($fp)) {
    $data = trim(stream_get_line($fp, 1024, "\n"));
        if ($przerwij==true) break;
        if ($stop==true) while ($stop==true){
                debug_log("Zzzz.","proc1");
                sleep(1);
        } // spimy gdy pora ;)
                fwrite($pipe, $data."\n");
                sleep(2);//opóżnienie dla obrazowania działania sygnałów
  } 
fclose($fp);
fclose ($pipe);
}
//----------------------------------------------------------------------------------------
function proc2(){
        global $sasiedzi,$stop,$start,$przerwij,$sig1,$sig2,$sig3,$sig4,$nrproc,$FIFO1,$FIFO2,$msg_key1,$msg_key2,$msg_key3;
        czekaj_SasiedziPID($msg_key2);
        $pipe=mkpipe($FIFO1,"r");
        $pipe2=mkpipe($FIFO2,"w");
        while (!feof($pipe)){
        if ($przerwij==true) break;
        if ($stop==true) while ($stop==true){
                debug_log("Zzzz.","proc2");
                sleep(1);
        } // spimy gdy pora ;)


        $data=trim(fgets($pipe));
        $cnt=strlen($data);
        fwrite($pipe2,$cnt."\n");
        }
        fclose($pipe);
        fclose($pipe2);
}
//----------------------------------------------------------------------------------------
function proc3(){
global $sasiedzi,$stop,$start,$przerwij,$sig1,$sig2,$sig3,$sig4,$nrproc,$FIFO1,$FIFO2,$msg_key1,$msg_key2,$msg_key3;
        czekaj_SasiedziPID($msg_key3);
        $pipe=mkpipe($FIFO2,"r");
        while (!feof($pipe)) {
                $data = trim(stream_get_line($pipe, 1024, "\n"));
                if (!empty($data)) echo "PROC3: data: $data\n";
        if ($przerwij==true) break;
        if ($stop==true) while ($stop==true){
                debug_log("Zzzz.","proc3");
                sleep(1);
        } // spimy gdy pora ;)
        }
        fclose($pipe);
}
//----------------------------------------------------------------------------------------


function proc_pm(){
global $sasiedzi,$stop,$start,$przerwij,$sig1,$sig2,$sig3,$sig4,$nrproc,$FIFO1,$FIFO2,$msg_key1,$msg_key2,$msg_key3;
        //* tworzenie kolejek dla porcesów potomnych;
        create_message_queue($msg_key1);
        //create_message_queue($msg_key2);
        //create_message_queue($msg_key3);
        $Proc1 = new Thread('proc1');
        $Proc2 = new Thread('proc2');
        $Proc3 = new Thread('proc3');


        $Proc1->addSignalHandler($sig1,'s1_handler');
        $Proc1->addSignalHandler($sig2,'s2_handler');
        $Proc1->addSignalHandler($sig3,'s3_handler');
        //$Proc1->addSignalHandler($sig4,'s4_handler');
        
        $Proc2->addSignalHandler($sig1,'s1_handler');
        $Proc2->addSignalHandler($sig2,'s2_handler');
        $Proc2->addSignalHandler($sig3,'s3_handler');
        //$Proc2->addSignalHandler($sig4,'s4_handler');
        
        $Proc3->addSignalHandler($sig1,'s1_handler');
        $Proc3->addSignalHandler($sig2,'s2_handler');
        $Proc3->addSignalHandler($sig3,'s3_handler');
        //$Proc3->addSignalHandler($sig4,'s4_handler');
        
        
        
        
        $Proc1->start();
        $sasiedzi[]=$Proc1->getPid();
        $Proc2->start();
        $sasiedzi[]=$Proc2->getPid();
        $Proc3->start();
        $sasiedzi[]=$Proc3->getPid();
        // wysyłanie PID sasiadow do oczekujacych w swoich kolejkach procesów potomnych
   // send_message($key, &$msg,$msgtype=1) 
           send_message($msg_key1,$sasiedzi);
    //send_message($msg_key2,$sasiedzi);
    //send_message($msg_key3,$sasiedzi);


while( $Proc1->isAlive() || $Proc2->isAlive() || $Proc3->isAlive()) {
          sleep(3);
}
destroy_message_queue($msg_key1);
//destroy_message_queue($msg_key2);
//destroy_message_queue($msg_key3);
}
//----------------------------------------------------------------------------------------
//zmienne globalne;
$logfile='/tmp/os_zadanie.log'; //plik do debugowania;
$debug=true;
$sasiedzi=array();//tablica pid dla wszystkich procesów;
// zmienne globalne do stetrowania pracą procesów potomnych;
$stop=false;$start=true;$przerwij=false; 
//zmienne globalne do definicji sygnałów;
$sig1=SIGTERM;
$sig2=SIGTSTP;
$sig3=SIGCONT;
$sig4=SIGUSR1;
$nrproc=0; // numer procesu który ma aktualnie wysłac sysgnał
$FIFO1='./fifo1';
$FIFO2='./fifo2';
$msg_key1='1111';
$msg_key2='2222';
$msg_key3='3333';
//global $sasiedzi,$stop,$start,$przerwij,$sig1,$sig2,$sig3,$sig4,$nrproc,$FIFO1,$FIFO2,$msg_key1,$msg_key2,$msg_key3;
//
                $ProcPM=new Thread('proc_pm');
        $ProcPM->addSignalHandler($sig1,'pm_handler');
        $ProcPM->addSignalHandler($sig2,'pm_handler');
        $ProcPM->addSignalHandler($sig3,'pm_handler');
        $ProcPM->start();
    


?>